/**
 @file sys_usw_qos_policer.c

 @date 2009-10-16

 @version v2.0

*/

/****************************************************************************
  *
  * Header Files
  *
  ****************************************************************************/
#include "ctc_error.h"
#include "ctc_const.h"
#include "ctc_macro.h"
#include "ctc_qos.h"
#include "ctc_debug.h"

#include "sys_usw_common.h"
#include "sys_usw_port.h"
#include "sys_usw_register.h"
#include "sys_usw_qos.h"
#include "sys_usw_qos_api.h"
#include "sys_usw_wb_common.h"
#include "sys_usw_acl_api.h"
#include "sys_usw_nexthop_api.h"

#include "drv_api.h"

/****************************************************************************
*
* Defines and Macros
*
****************************************************************************/
#define SYS_QOS_INIT_CHECK() \
    do { \
        LCHIP_CHECK(lchip); \
        if (NULL == p_usw_qos_master[lchip]){ \
            return CTC_E_NOT_INIT;\
        } \
    } while (0)

/****************************************************************************
*
* Data structures
*
****************************************************************************/
/**
 @brief  Define sys layer qos global configure data structure
*/


/****************************************************************************
 *
* Global and Declaration
*
*****************************************************************************/
sys_qos_master_t* p_usw_qos_master[CTC_MAX_LOCAL_CHIP_NUM_PP] = {NULL};
#define QOS_LOCK \
    if (p_usw_qos_master[lchip]->p_qos_mutex) sal_mutex_lock(p_usw_qos_master[lchip]->p_qos_mutex)
#define QOS_UNLOCK \
    if (p_usw_qos_master[lchip]->p_qos_mutex) sal_mutex_unlock(p_usw_qos_master[lchip]->p_qos_mutex)
/****************************************************************************
 *
* Function
*
*****************************************************************************/
extern int32
sys_usw_qos_update_cpu_reason(uint8 lchip, uint8 remote_gchip, uint8 trunk_id);
extern int32
sys_usw_qos_fcdl_get_recover_state(uint8 lchip, uint32 gport, uint8 pri_class, uint8* state);
/*global param*/
STATIC int32
_sys_usw_qos_set_global_config_before_at(uint8 lchip, ctc_qos_glb_cfg_t* p_glb_cfg, sys_nh_info_dsnh_t* p_nhinfo)
{
    int32 ret = CTC_E_NONE;
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    switch (p_glb_cfg->cfg_type)
    {
    case CTC_QOS_GLB_CFG_RESRC_MGR_EN:
        ret = sys_usw_qos_resrc_mgr_en(lchip, p_glb_cfg->u.value);
        break;

    case CTC_QOS_GLB_CFG_SHAPE_PKT_EN:
        ret = sys_usw_qos_set_port_shp_base_pkt_en(lchip, p_glb_cfg->u.value);
        break;

    case CTC_QOS_GLB_CFG_REASON_SHAPE_PKT_EN:
        ret = sys_usw_qos_set_reason_shp_base_pkt_en(lchip, p_glb_cfg->u.value);
        break;

    case CTC_QOS_GLB_CFG_QUEUE_DROP_MONITOR_EN:
        ret = sys_usw_qos_set_monitor_drop_queue_id(lchip, &(p_glb_cfg->u.drop_monitor), p_nhinfo);
        break;

    case CTC_QOS_GLB_CFG_SCH_WRR_EN:
        ret = sys_usw_qos_set_sch_wrr_enable(lchip, p_glb_cfg->u.value);
        break;
    case CTC_QOS_GLB_CFG_FCDL_INTERVAL:
        ret = sys_usw_qos_set_fcdl_interval(lchip, p_glb_cfg->u.value);
        break;
    case CTC_QOS_GLB_CFG_OOBFC:
        ret = DRV_IS_TMG(lchip) ? CTC_E_NOT_SUPPORT : sys_usw_qos_set_oobfc(lchip, &p_glb_cfg->u.oobfc);
        break;
    case CTC_QOS_GLB_CFG_FCDL_ACTION:
        ret = sys_usw_qos_set_fcdl_action(lchip, p_glb_cfg->u.value);
        break;
    default:
        ret = CTC_E_NOT_SUPPORT;
        break;
    }
    return ret;
}
STATIC int32
_sys_usw_qos_get_global_config_before_at(uint8 lchip, ctc_qos_glb_cfg_t* p_glb_cfg)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    switch (p_glb_cfg->cfg_type)
    {
    case CTC_QOS_GLB_CFG_QUEUE_DROP_MONITOR_EN:
        ret = sys_usw_qos_get_monitor_drop_queue_id(lchip, &(p_glb_cfg->u.drop_monitor));
        break;
    case CTC_QOS_GLB_CFG_OOBFC:
        ret = DRV_IS_TMG(lchip) ? CTC_E_NOT_SUPPORT : sys_usw_qos_get_oobfc(lchip, &p_glb_cfg->u.oobfc);
        break;
    case CTC_QOS_GLB_CFG_FCDL_ACTION:
        ret = sys_usw_qos_get_fcdl_action(lchip, &p_glb_cfg->u.value);
        break;
    default:
        ret = CTC_E_NOT_SUPPORT;
        break;
    }

    return ret;
}

int32
_sys_usw_qos_init_before_at(uint8 lchip, void* p_glb_parm)
{
    int32 ret = CTC_E_NONE;

    /*sys qos api register*/


    if(DRV_IS_TSINGMA(lchip) && (DRV_CHIP_SUB_TYPE_1 != DRV_CHIP_SUB_TYPE(lchip)))
    {
        uint32 field_val;
        uint32 cmd = DRV_IOR(ShareBufferCtl_t, ShareBufferCtl_cfgShareTableEn_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));
        MCHIP_CAP(SYS_CAP_QOS_DROP_TOTAL_POOL_SIZE) = field_val ? 16384:MCHIP_CAP(SYS_CAP_QOS_DROP_TOTAL_POOL_SIZE);
        MCHIP_CAP(SYS_CAP_QOS_DROP_IGS_DEFAULT_POOL_SIZE) = field_val ? 12544:MCHIP_CAP(SYS_CAP_QOS_DROP_IGS_DEFAULT_POOL_SIZE);
    }

    CTC_ERROR_GOTO(sys_usw_qos_class_init(lchip), ret, error2);
    CTC_ERROR_GOTO(sys_usw_qos_policer_init(lchip, p_glb_parm), ret, error3);
    CTC_ERROR_GOTO(sys_usw_queue_enq_init(lchip, p_glb_parm), ret, error4);
    CTC_ERROR_GOTO(sys_usw_queue_sch_init(lchip), ret, error5);
    CTC_ERROR_GOTO(sys_usw_queue_shape_init(lchip), ret, error6);
    CTC_ERROR_GOTO(sys_usw_queue_drop_init(lchip, p_glb_parm), ret, error7);
    CTC_ERROR_GOTO(sys_usw_queue_cpu_reason_init(lchip), ret, error8);
    CTC_ERROR_GOTO(SYS_CB_REGISTER(lchip, SYS_CB_QOS_UPDATE_TRUNK_BY_RCHIP, sys_usw_qos_update_cpu_reason), ret, error9);

    return CTC_E_NONE;
error9:
    (void)sys_usw_queue_cpu_reason_deinit(lchip);
error8:
    (void)sys_usw_queue_drop_deinit(lchip);
error7:
    (void)sys_usw_queue_shape_deinit(lchip);
error6:
    (void)sys_usw_queue_sch_deinit(lchip);
error5:
    (void)sys_usw_queue_enq_deinit(lchip);
error4:
    (void)sys_usw_qos_policer_deinit(lchip);
error3:
    (void)sys_usw_qos_class_deinit(lchip);
error2:
    return ret;
}

int32
_sys_usw_qos_deinit_before_at(uint8 lchip)
{
    sys_usw_queue_cpu_reason_deinit(lchip);

    sys_usw_queue_drop_deinit(lchip);

    sys_usw_queue_sch_deinit(lchip);

    sys_usw_queue_shape_deinit(lchip);

    sys_usw_queue_enq_deinit(lchip);

    sys_usw_qos_policer_deinit(lchip);

    sys_usw_qos_class_deinit(lchip);
    return CTC_E_NONE;
}

int32
sys_usw_qos_api_cb_register_before_at(uint8 lchip, void** api_cb)
{
    CTC_PTR_VALID_CHECK(api_cb);
    api_cb[SYS_QOS_API_INIT] = _sys_usw_qos_init_before_at;
    api_cb[SYS_QOS_API_DEINIT] = _sys_usw_qos_deinit_before_at;

    api_cb[SYS_QOS_API_GET_CHAN_BY_PORT] = _sys_usw_get_channel_by_port;
    api_cb[SYS_QOS_API_ADD_PORT_TO_CHAN] = _sys_usw_add_port_to_channel;
    api_cb[SYS_QOS_API_REMOVE_PORT_FROM_CHAN] = _sys_usw_remove_port_from_channel;
    api_cb[SYS_QOS_API_ADD_EXT_PORT_TO_CHAN] = _sys_usw_qos_add_extend_port_to_channel;
    api_cb[SYS_QOS_API_REMOVE_EXT_PORT_FROM_CHAN] = _sys_usw_qos_remove_extend_port_to_channel;
    api_cb[SYS_QOS_API_ADD_MCAST_QUE_TO_CHAN] = _sys_usw_qos_add_mcast_queue_to_channel;
    api_cb[SYS_QOS_API_REMOVE_MCAST_QUE_FROM_CHAN] = _sys_usw_qos_remove_mcast_queue_to_channel;
    api_cb[SYS_QOS_API_SET_MC_QUE_HIGH_PRI_EN] = _sys_usw_qos_set_mc_queue_high_priority_en;
    api_cb[SYS_QOS_API_QUE_SET_PORT_DROP_EN] = _sys_usw_queue_set_port_drop_en;
    api_cb[SYS_QOS_API_QUE_GET_PROFILE_FROM_HW] = _sys_usw_queue_get_profile_from_hw;
    api_cb[SYS_QOS_API_SET_DMA_CHAN_DROP_EN] = _sys_usw_set_dma_channel_drop_en;
    api_cb[SYS_QOS_API_SET_AQMSCAN_HIGH_PRI_EN] = _sys_usw_qos_set_aqmscan_high_priority_en;
    api_cb[SYS_QOS_API_QUE_GET_PORT_DEPTH] = _sys_usw_queue_get_port_depth;
    api_cb[SYS_QOS_API_QUE_ADD_FOR_STACKING] = _sys_usw_queue_add_for_stacking;
    api_cb[SYS_QOS_API_QUE_REMOVE_FOR_STACKING] = _sys_usw_queue_remove_for_stacking;
    api_cb[SYS_QOS_API_BIND_SERVICE_LOGIC_DSTPORT] = _sys_usw_qos_bind_service_logic_dstport;
    api_cb[SYS_QOS_API_UNBIND_SERVICE_LOGIC_DSTPORT] = _sys_usw_qos_unbind_service_logic_dstport;
    api_cb[SYS_QOS_API_BIND_SERVICE_LOGIC_SRCPORT] = _sys_usw_qos_bind_service_logic_srcport;
    api_cb[SYS_QOS_API_UNBIND_SERVICE_LOGIC_SRCPORT] = _sys_usw_qos_unbind_service_logic_srcport;
    api_cb[SYS_QOS_API_SET_DROP_RESRC_CHK_MODE] = sys_usw_qos_set_resrc_check_mode;
    api_cb[SYS_QOS_API_SET_FC_DEFAULT_PROFILE] = _sys_usw_qos_set_fc_default_profile;
    api_cb[SYS_QOS_API_QUE_GET_QUE_ID] = sys_usw_queue_get_queue_id;
    api_cb[SYS_QOS_API_QUE_ID_GET_QUE] = sys_usw_queue_id_get_queue;
    api_cb[SYS_QOS_API_GET_CHAN_BY_QUE_ID] = sys_usw_get_channel_by_queue_id;
    api_cb[SYS_QOS_API_QUE_DUMP] = _sys_usw_qos_queue_dump;
    api_cb[SYS_QOS_API_GROUP_DUMP] = _sys_usw_qos_group_dump;
    api_cb[SYS_QOS_API_PORT_DUMP] = _sys_usw_qos_port_dump;
    api_cb[SYS_QOS_API_SERVICE_DUMP] = _sys_usw_qos_service_dump;
    api_cb[SYS_QOS_API_DUMP_STATUS] = _sys_usw_qos_dump_status;
    api_cb[SYS_QOS_API_SET_SHAPE] = _sys_usw_qos_set_shape;
    api_cb[SYS_QOS_API_GET_SHAPE] = _sys_usw_qos_get_shape;
    api_cb[SYS_QOS_API_SET_SCHED] = _sys_usw_qos_set_sched;
    api_cb[SYS_QOS_API_GET_SCHED] = _sys_usw_qos_get_sched;
    api_cb[SYS_QOS_API_SET_GLB_CFG] = _sys_usw_qos_set_global_config_before_at;
    api_cb[SYS_QOS_API_GET_GLB_CFG] = _sys_usw_qos_get_global_config_before_at;
    api_cb[SYS_QOS_API_SET_QUE] = sys_usw_qos_queue_set;
    api_cb[SYS_QOS_API_GET_QUE] = sys_usw_qos_queue_get;
    api_cb[SYS_QOS_API_SET_DROP] = sys_usw_queue_set_drop;
    api_cb[SYS_QOS_API_GET_DROP] = sys_usw_queue_get_drop;
    api_cb[SYS_QOS_API_SET_RESRC] = sys_usw_queue_set_resrc;
    api_cb[SYS_QOS_API_GET_RESRC] = sys_usw_queue_get_resrc;
    api_cb[SYS_QOS_API_QUERY_POOL_STATS] = sys_usw_queue_query_pool_stats;
    api_cb[SYS_QOS_API_QUERY_QUE_STATS] = sys_usw_queue_stats_query;
    api_cb[SYS_QOS_API_CLEAR_QUE_STATS] = sys_usw_queue_stats_clear;
    api_cb[SYS_QOS_API_SET_EGS_RESRC_GUARANTEE] = _sys_usw_queue_set_egs_resrc_guarantee;
    api_cb[SYS_QOS_API_TRAVERSE_QUEUE_NODE] = _sys_usw_queue_traverse_queue_node;
    return CTC_E_NONE;
}

#define __1_QOS_WB__

int32
sys_usw_qos_wb_sync(uint8 lchip,uint32 app_id)
{
    int32 ret = CTC_E_NONE;
    ctc_wb_data_t wb_data = {0};
    sys_wb_qos_master_t *p_wb_qos_master = NULL;

    CTC_WB_ALLOC_BUFFER(&wb_data.buffer);
    QOS_LOCK;

    if(!SYS_VCHIP_PP_IS_NOT_BASE(lchip))
    {
        if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_QOS_SUBID_MASTER)
        {
            /* matser */
            CTC_WB_INIT_DATA_T((&wb_data), sys_wb_qos_master_t, CTC_FEATURE_QOS, SYS_WB_APPID_QOS_SUBID_MASTER);

            p_wb_qos_master = (sys_wb_qos_master_t *)wb_data.buffer;
            sal_memset(p_wb_qos_master, 0, sizeof(sys_wb_qos_master_t));

            p_wb_qos_master->lchip = lchip;
            p_wb_qos_master->version = SYS_WB_VERSION_QOS;

            wb_data.valid_cnt = 1;
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
            CTC_WB_SYNC_END_DATA(CTC_FEATURE_QOS, SYS_WB_APPID_QOS_SUBID_MASTER);
        }

        /* queue */
        CTC_ERROR_GOTO(sys_usw_queue_wb_sync(lchip, app_id, &wb_data), ret, done);
    }

    /* policer */
    CTC_ERROR_GOTO(sys_usw_qos_policer_wb_sync(lchip, app_id, &wb_data), ret, done);

done:
    QOS_UNLOCK;
    CTC_WB_FREE_BUFFER(wb_data.buffer);

    return ret;
}

int32
sys_usw_qos_wb_restore(uint8 lchip)
{
    int32 ret = CTC_E_NONE;
    uint8 pp_id = 0;
    uint8 pp_base = SYS_PP_BASE(lchip);
    ctc_wb_query_t wb_query;
    sys_wb_qos_master_t wb_qos_master;

    CTC_WB_ALLOC_BUFFER(&wb_query.buffer);

    /* master */
    CTC_WB_INIT_QUERY_T((&wb_query), sys_wb_qos_master_t, CTC_FEATURE_QOS, SYS_WB_APPID_QOS_SUBID_MASTER);

    sal_memset(&wb_qos_master, 0, sizeof(sys_wb_qos_master_t));

    CTC_ERROR_GOTO(ctc_wb_query_entry(&wb_query), ret, done);
    if ((wb_query.valid_cnt != 1) || (wb_query.is_end != 1))
    {
        CTC_WB_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "query qos master error! valid_cnt: %d, is_end: %d.\n", wb_query.valid_cnt, wb_query.is_end);
        ret = CTC_E_NONE;
        goto done;
    }

    sal_memcpy((uint8 *)&wb_qos_master, (uint8 *)wb_query.buffer, wb_query.key_len + wb_query.data_len);

    if (CTC_WB_VERSION_CHECK(SYS_WB_VERSION_QOS, wb_qos_master.version))
    {
        CTC_ERROR_GOTO(CTC_E_VERSION_MISMATCH, ret, done);
    }

    /* policer */
    for (pp_id = 0; pp_id < SYS_PP_NUM(lchip); pp_id++)
    {
        CTC_ERROR_GOTO(sys_usw_qos_policer_wb_restore(pp_id+pp_base, &wb_query), ret, done);
    }

    /* queue */
    CTC_ERROR_GOTO(sys_usw_queue_wb_restore(lchip, &wb_query), ret, done);

done:
   CTC_WB_FREE_BUFFER(wb_query.buffer);

    return ret;
}

STATIC int32
_sys_usw_qos_wb_init(uint8 lchip)
{
    uint16 copp_plc_num = 0;
    uint8 pp_id = 0;
    uint8 pp_base = SYS_PP_BASE(lchip);
    ctc_wb_appid_t  appid;
    sal_memset(&appid, 0, sizeof(appid));

    appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_QOS, SYS_WB_APPID_QOS_SUBID_MASTER) ;
    appid.entry_num = 1;
    appid.entry_size  = sizeof(sys_wb_qos_master_t);
    appid.rt_en = 0;
    ctc_wb_add_appid( lchip, &appid);

    /* init multi PP module */
    for (pp_id = 0; pp_id < SYS_PP_NUM(lchip); pp_id++)
    {
        appid.app_id = (pp_id+pp_base) << 16 | CTC_WB_APPID(CTC_FEATURE_QOS, SYS_WB_APPID_QOS_SUBID_POLICER) ;
        copp_plc_num = (DRV_TABLE_MAX_INDEX(pp_id+pp_base , DsIpeCoPPConfig_t) + DRV_TABLE_MAX_INDEX(pp_id+pp_base, DsEpeCoPPConfig_t))*2;
        appid.entry_num = ((DRV_FROM_TMM(pp_id+pp_base) ? MCHIP_CAP(SYS_CAP_QOS_POLICER_POLICER_NUM)
                         : (MCHIP_CAP(SYS_CAP_QOS_POLICER_POLICER_NUM)*2)) + copp_plc_num);
        appid.entry_size  = sizeof(sys_wb_qos_policer_t);
        appid.rt_en = 0;
        ctc_wb_add_appid( pp_id+pp_base, &appid);
    }

    appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_QOS, SYS_WB_APPID_QOS_SUBID_QUEUE_MASTER) ;
    appid.entry_num = 1;
    appid.entry_size  = sizeof(sys_wb_qos_queue_master_t);
    appid.rt_en = 0;
    ctc_wb_add_appid( lchip, &appid);

    if(!(DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)))
    {
        appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_QOS, SYS_WB_APPID_QOS_SUBID_QUEUE_FC_PROFILE) ;
        appid.entry_num = MCHIP_CAP(SYS_CAP_CHANID_MAX)*2;
        appid.entry_size  = sizeof(sys_wb_qos_queue_fc_profile_t);
        appid.rt_en = 0;
        ctc_wb_add_appid( lchip, &appid);

        appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_QOS, SYS_WB_APPID_QOS_SUBID_QUEUE_PFC_PROFILE) ;
        appid.entry_num = MCHIP_CAP(SYS_CAP_CHANID_MAX)*2*8;
        appid.entry_size  = sizeof(sys_wb_qos_queue_pfc_profile_t);
        appid.rt_en = 0;
        ctc_wb_add_appid( lchip, &appid);
    }

    if (DRV_FROM_TMM(lchip))
    {
        appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_QOS, SYS_WB_APPID_QOS_SUBID_QUEUE_SCH_GROUP_NODE) ;
        appid.entry_num = MCHIP_CAP(SYS_CAP_QOS_L0_GRP_NUM) + MCHIP_CAP(SYS_CAP_QOS_L1_GRP_NUM) + MCHIP_CAP(SYS_CAP_QOS_L2_GRP_NUM) + MCHIP_CAP(SYS_CAP_QOS_L3_GRP_NUM) + MCHIP_CAP(SYS_CAP_QOS_QUE_GRP_NUM);
        appid.entry_size  = sizeof(sys_wb_qos_queue_sch_group_node_t);
        appid.rt_en = 0;
        ctc_wb_add_appid( lchip, &appid);
        /* init multi PP module */
        for (pp_id = 0; pp_id < SYS_PP_NUM(lchip); pp_id++)
        {
            appid.app_id = (pp_id+pp_base) << 16 | CTC_WB_APPID(CTC_FEATURE_QOS, SYS_WB_APPID_QOS_SUBID_POLICER_SVC) ;
            appid.entry_num = MCHIP_CAP(SYS_CAP_QOS_POLICER_SVC_POLICER_NUM);
            appid.entry_size  = sizeof(sys_wb_qos_policer_svc_t);
            appid.rt_en = 0;
            ctc_wb_add_appid( pp_id+pp_base, &appid);
        }
    }
    else if (!DRV_FROM_TMM(lchip))
    {
        appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_QOS, SYS_WB_APPID_QOS_SUBID_QUEUE_GROUP_NODE) ;
        appid.entry_num = MCHIP_CAP(SYS_CAP_QOS_EXT_QUEUE_GRP_NUM);
        appid.entry_size  = sizeof(sys_wb_qos_queue_group_node_t);
        appid.rt_en = 0;
        ctc_wb_add_appid( lchip, &appid);



        appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_QOS, SYS_WB_APPID_QOS_SUBID_QUEUE_FC_DROPTH_PROFILE) ;
        appid.entry_num = MCHIP_CAP(SYS_CAP_CHANID_MAX)*2;
        appid.entry_size  = sizeof(sys_wb_qos_queue_fc_profile_t);
        appid.rt_en = 0;
        ctc_wb_add_appid( lchip, &appid);

        appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_QOS, SYS_WB_APPID_QOS_SUBID_QUEUE_PFC_DROPTH_PROFILE) ;
        appid.entry_num = MCHIP_CAP(SYS_CAP_CHANID_MAX)*2*8;
        appid.entry_size  = sizeof(sys_wb_qos_queue_pfc_profile_t);
        appid.rt_en = 0;
        ctc_wb_add_appid( lchip, &appid);

        appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_QOS, SYS_WB_APPID_QOS_SUBID_QUEUE_OOBFC_PROFILE) ;
        appid.entry_num = MCHIP_CAP(SYS_CAP_CHANID_MAX);
        appid.entry_size  = sizeof(sys_wb_qos_queue_oobfc_profile_t);
        appid.rt_en = 0;
        ctc_wb_add_appid( lchip, &appid);
    }

    appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_QOS, SYS_WB_APPID_QOS_SUBID_QUEUE_PORT_EXTENDER) ;
    appid.entry_num = MCHIP_CAP(SYS_CAP_QOS_EXT_QUEUE_GRP_NUM);
    appid.entry_size  = sizeof(sys_wb_qos_queue_port_extender_t);
    appid.rt_en = 0;
    ctc_wb_add_appid( lchip, &appid);

    appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_QOS, SYS_WB_APPID_QOS_SUBID_CPU_REASON) ;
    appid.entry_num = CTC_PKT_CPU_REASON_MAX_COUNT;
    appid.entry_size  = sizeof(sys_wb_qos_cpu_reason_t);
    appid.rt_en = 0;
    ctc_wb_add_appid( lchip, &appid);

    if(!DRV_FROM_AT(lchip))
    {
        appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_QOS, SYS_WB_APPID_QOS_SUBID_QUEUE_LOGIC_SRC_PORT) ;
        appid.entry_num = MCHIP_CAP(SYS_CAP_QOS_EXT_QUEUE_GRP_NUM);
        appid.entry_size  = sizeof(sys_wb_qos_logicsrc_port_t);
        appid.rt_en = 0;
        ctc_wb_add_appid( lchip, &appid);
        
        appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_QOS, SYS_WB_APPID_QOS_SUBID_QUEUE_DESTPORT) ;
        appid.entry_num = MCHIP_CAP(SYS_CAP_QOS_EXT_QUEUE_GRP_NUM);
        appid.entry_size  = sizeof(sys_wb_qos_destport_t);
        appid.rt_en = 0;
        ctc_wb_add_appid( lchip, &appid);
    }
#if 0
    /* init multi PP module */
    for (pp_id = 0; pp_id < SYS_PP_NUM(lchip); pp_id++)
    {
        appid.app_id = (pp_id+pp_base) << 16 | CTC_WB_APPID(CTC_FEATURE_QOS, SYS_WB_APPID_QOS_SUBID_POLICER_PROFILE) ;
        appid.entry_num = ((DRV_FROM_TMM(pp_id+pp_base) ? MCHIP_CAP(SYS_CAP_QOS_POLICER_POLICER_NUM)
                                              : (MCHIP_CAP(SYS_CAP_QOS_POLICER_POLICER_NUM)*2)) + copp_plc_num);
        appid.entry_size  = sizeof(sys_wb_qos_policer_profile_t);
        appid.rt_en = 0;
        ctc_wb_add_appid( pp_id+pp_base, &appid);
    }
#endif
    appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_QOS, SYS_WB_APPID_QOS_SUBID_QUEUE_FCDL) ;
    appid.entry_num = MCHIP_CAP(SYS_CAP_PORT_NUM_PER_CHIP);
    appid.entry_size  = sizeof(sys_wb_qos_queue_fcdl_t);
    appid.rt_en = 0;
    ctc_wb_add_appid( lchip, &appid);

    return CTC_E_NONE;
}

int32
sys_usw_qos_dump_db(uint8 lchip, sal_file_t p_f,ctc_global_dump_db_t* p_dump_param)
{
    int32 ret = CTC_E_NONE;

    QOS_LOCK;
    /* policer */
    ret = sys_usw_qos_policer_dump_db(lchip, p_f,p_dump_param);

    /* queue */
    ret = sys_usw_qos_queue_dump_db(lchip, p_f,p_dump_param);
    QOS_UNLOCK;

    return ret;
}

#define __2_QOS_SYS_API__

/* policer */

#if 0
int32
sys_usw_qos_policer_id_check(uint8 lchip, uint16 policer_id, uint8 sys_policer_type, uint8* p_is_bwp)
{
    int32 ret = CTC_E_NONE;
    sys_qos_policer_param_t policer_param;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    sal_memset(&policer_param, 0, sizeof(policer_param));
    policer_param.glb_policer = 0;
    policer_param.policer_id  = policer_id;
    policer_param.sys_policer_type = sys_policer_type;
    ret = _sys_usw_qos_policer_alloc_and_install(lchip, &policer_param);
    if (p_is_bwp)
    {
        *p_is_bwp = policer_param.is_bwp;
    }

    QOS_UNLOCK;

    return ret;
}
#endif

int32
sys_usw_qos_policer_group_bind(uint8 lchip,sys_qos_policer_group_info_t* p_policer_group_info)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = _sys_usw_qos_policer_group_bind(lchip, p_policer_group_info);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_policer_group_check_bind(uint8 lchip,sys_qos_policer_group_info_t* p_policer_group_info)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = _sys_usw_qos_policer_group_check_bind(lchip, p_policer_group_info);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_policer_group_unbind(uint8 lchip,sys_qos_policer_group_info_t* p_policer_group_info)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = _sys_usw_qos_policer_group_unbind(lchip, p_policer_group_info);

    QOS_UNLOCK;

    return ret;
}
int32
sys_usw_qos_policer_svc_stmctl_set_cfg(uint8 lchip, uint8 mstorm_ctl_mode, uint8 ipg_en)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = _sys_usw_qos_policer_svc_stmctl_set_cfg(lchip, mstorm_ctl_mode, ipg_en);

    QOS_UNLOCK;

    return ret;
}
int32
sys_usw_qos_policer_svc_mode_check(uint8 lchip, uint8 op, uint8 is_stmctl , uint8* sup)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = _sys_usw_qos_policer_svc_mode_check(lchip, op, is_stmctl, sup);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_policer_svc_stmctl_set(uint8 lchip, sys_qos_api_svc_stmctl_cfg_t* svc_storm_cfg)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = _sys_usw_qos_policer_svc_stmctl_set(lchip, svc_storm_cfg);

    QOS_UNLOCK;

    return ret;
}
int32
sys_usw_qos_policer_svc_stmctl_get(uint8 lchip, sys_qos_api_svc_stmctl_cfg_t* svc_stmctl_cfg)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = _sys_usw_qos_policer_svc_stmctl_get(lchip, svc_stmctl_cfg);

    QOS_UNLOCK;

    return ret;
}
int32
sys_usw_qos_policer_index_get(uint8 lchip, sys_qos_policer_param_t* p_policer_param)
{
    int32 ret = CTC_E_NONE;
    uint8 lchip_start = lchip;
    uint8 loop_end    = lchip + 1;
    uint8 index1       = 0;
    uint8 index2       = 0;

    SYS_QOS_INIT_CHECK();

    if(p_policer_param->glb_policer)
    {
        lchip_start = SYS_PP_BASE(lchip);
        loop_end    = SYS_PP_BASE(lchip) + SYS_PP_NUM(lchip);
    }

    if(!p_policer_param->internal_use)
    {
        QOS_LOCK;
    }

    for(index1 = lchip_start; index1 < loop_end; index1++)
    {
        ret = _sys_usw_qos_policer_alloc_and_install(index1, p_policer_param);
        if (ret != CTC_E_NONE)
        {
            break;
        }
    }

    if(index1 != loop_end)
    {
        for(index2 = lchip_start; index2 < index1; index2++)
        {
            CTC_ERROR_DUMP(_sys_usw_qos_policer_free_and_uninstall(index2, p_policer_param));
        }
    }

    if(!p_policer_param->internal_use)
    {
        QOS_UNLOCK;
    }

    return ret;
}

int32
sys_usw_qos_policer_ingress_vlan_get(uint8 lchip, uint16* ingress_vlan_policer_num)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = _sys_usw_qos_policer_ingress_vlan_get(lchip, ingress_vlan_policer_num);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_policer_egress_vlan_get(uint8 lchip, uint16* egress_vlan_policer_num)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = _sys_usw_qos_policer_egress_vlan_get(lchip, egress_vlan_policer_num);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_policer_map_token_rate_user_to_hw(uint8 lchip, uint8 is_pps,
                                             uint32 user_rate, /*kb/s*/
                                             uint32 *hw_rate,
                                             uint16 bit_with,
                                             uint32 gran,
                                             uint32 upd_freq)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = _sys_usw_qos_policer_map_token_rate_user_to_hw(lchip,
                                                is_pps, user_rate, hw_rate, bit_with, gran, upd_freq);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_policer_map_token_rate_hw_to_user(uint8 lchip, uint8 is_pps,
                                                    uint32 hw_rate, uint32 *user_rate, uint32 upd_freq)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret =_sys_usw_qos_policer_map_token_rate_hw_to_user(lchip,
                                                    is_pps, hw_rate, user_rate, upd_freq);

    QOS_UNLOCK;

    return ret;
}

/* queue enq */
int32
sys_usw_queue_get_enq_mode(uint8 lchip, uint8 *enq_mode)
{
    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    *enq_mode = _sys_usw_queue_get_enq_mode(lchip);

    QOS_UNLOCK;

    return CTC_E_NONE;
}

int32
sys_usw_queue_get_service_queue_mode(uint8 lchip, uint8 *service_queue_mode)
{
    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    *service_queue_mode = _sys_usw_queue_get_service_queue_mode(lchip);

    QOS_UNLOCK;

    return CTC_E_NONE;
}

int32
sys_usw_get_channel_by_sub_chan(uint8 lchip, uint8 dp_id, uint8 sub_chan, uint16 *channel)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_GET_CHAN_BY_SUB_CHAN,
                                            lchip, dp_id, sub_chan, channel);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_get_channel_by_port(uint8 lchip, uint32 gport, uint16 *channel)/*for AT, return ppPort*/
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_GET_CHAN_BY_PORT, lchip, gport, channel);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_add_port_to_channel(uint8 lchip, uint16 lport, uint16 channel, uint8 is_pp)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_ADD_PORT_TO_CHAN, lchip, lport, channel, is_pp);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_remove_port_from_channel(uint8 lchip, uint16 lport, uint16 channel)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_REMOVE_PORT_FROM_CHAN, lchip, lport, channel);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_add_extend_port_to_channel(uint8 lchip, uint16 lport, uint32 gport)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_ADD_EXT_PORT_TO_CHAN, lchip, lport, gport);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_remove_extend_port_to_channel(uint8 lchip, uint16 lport, uint32 gport)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;


    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_REMOVE_EXT_PORT_FROM_CHAN,
                        lchip, lport, gport);


    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_add_mcast_queue_to_channel(uint8 lchip, uint16 lport, uint8 channel)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();
    QOS_LOCK;
    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_ADD_MCAST_QUE_TO_CHAN,
                        lchip, lport, channel, 0);
    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_remove_mcast_queue_to_channel(uint8 lchip, uint16 lport, uint8 channel)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();
    QOS_LOCK;
    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_REMOVE_MCAST_QUE_FROM_CHAN,
                        lchip, lport, channel);
    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_set_mc_queue_high_priority_en(uint8 lchip)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();
    QOS_LOCK;
    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_SET_MC_QUE_HIGH_PRI_EN,
                        lchip);
    QOS_UNLOCK;

    return ret;
}
/* queue shape */
#if 0
int32
sys_usw_queue_shp_set_group_shape(uint8 lchip, ctc_qos_shape_group_t* p_shape)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = _sys_usw_queue_shp_set_group_shape(lchip, p_shape);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_get_port_shape_profile(uint8 lchip, uint32 gport, uint32* rate, uint32* thrd, uint8* p_shp_en)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = _sys_usw_qos_get_port_shape_profile(lchip, gport, rate, thrd, p_shp_en);

    QOS_UNLOCK;

    return ret;
}
#endif
int32
sys_usw_qos_map_token_thrd_user_to_hw(uint8 lchip, uint32  user_bucket_thrd,
                                            uint32 *hw_bucket_thrd,
                                            uint8 shift_bits,
                                            uint32 max_thrd)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = _sys_usw_qos_map_token_thrd_user_to_hw(lchip, user_bucket_thrd, hw_bucket_thrd, shift_bits, max_thrd);

    QOS_UNLOCK;

    return ret;
}
#if 0
int32
sys_usw_qos_map_token_thrd_hw_to_user(uint8 lchip, uint32  *user_bucket_thrd,
                                            uint16 hw_bucket_thrd,
                                            uint8 shift_bits)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = _sys_usw_qos_map_token_thrd_hw_to_user(lchip, user_bucket_thrd,
                                                                                        hw_bucket_thrd, shift_bits);

    QOS_UNLOCK;

    return ret;
}
#endif
/* queue drop */
int32
sys_usw_queue_set_port_drop_en(uint8 lchip, uint32 gport, bool enable, void* p_drop_param)
{
    int32 ret = CTC_E_NONE;
    uint32 chan_id[SYS_USW_MAX_CHANEL_NUM_PER_PORT] = {0};
    uint8 index1 = 0;
    uint8 index2 = 0;
    uint8 chan_num = 0;

    SYS_QOS_INIT_CHECK();
    CTC_ERROR_RETURN(sys_usw_port_api_get_channel(lchip, 0, gport, chan_id, &chan_num));
    QOS_LOCK;

    if(CTC_IS_MCHAN_PORT(gport))
    {
        ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_QUE_SET_PORT_DROP_EN,
                                 lchip, chan_id[0], enable, p_drop_param);
    }
    else
    {
        for (index1 = 0; index1 < chan_num; index1++)
        {
            ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_QUE_SET_PORT_DROP_EN,
                                 lchip, chan_id[index1], enable, p_drop_param);
            if (ret != CTC_E_NONE)
            {
                break;
            }
        }
        if (index1 != chan_num)
        {
            for (index2 = 0; index2 < index1; index2++)
            {
                ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_QUE_SET_PORT_DROP_EN,
                                     lchip, chan_id[index2], !enable, p_drop_param);
            }
        }
    }
    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_queue_get_profile_from_hw(uint8 lchip, uint32 gport, sys_qos_shape_profile_t* p_shp_profile)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();
    if (DRV_FROM_TMM(lchip))
    {
        return CTC_E_NONE;
    }
    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_QUE_GET_PROFILE_FROM_HW,
                        lchip, gport, p_shp_profile);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_set_dma_channel_drop_en(uint8 lchip, bool enable)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_SET_DMA_CHAN_DROP_EN,
                        lchip, enable);
    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_set_aqmscan_high_priority_en(uint8 lchip, bool enable)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_SET_AQMSCAN_HIGH_PRI_EN,
                        lchip, enable);
    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_queue_get_port_depth(uint8 lchip, uint32 gport, uint32* p_depth)
{
    int32 ret = CTC_E_NONE;
    uint32 chan_id[SYS_USW_MAX_CHANEL_NUM_PER_PORT] = {0};
    uint8 index = 0;
    uint32 q_depth_tmp = 0;
    uint8 chan_num = 0;

    SYS_QOS_INIT_CHECK();
    CTC_ERROR_RETURN(sys_usw_port_api_get_channel(lchip, 0, gport, chan_id, &chan_num));
    QOS_LOCK;
    *p_depth = 0;
    if(CTC_IS_MCHAN_PORT(gport))
    {
        ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_QUE_GET_PORT_DEPTH,
                                    lchip, chan_id[0], &q_depth_tmp);
        *p_depth = q_depth_tmp;
    }
    else
    {
        for (index = 0; index < chan_num; index++)
        {
            ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_QUE_GET_PORT_DEPTH,
                                    lchip, chan_id[index], &q_depth_tmp);
            *p_depth += q_depth_tmp;
        }
    }
    QOS_UNLOCK;

    return ret;
}

/* cpu reason */
int32
sys_usw_get_sub_queue_id_by_cpu_reason(uint8 lchip, uint16 reason_id, uint16* sub_queue_id)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = _sys_usw_get_sub_queue_id_by_cpu_reason(lchip, reason_id, sub_queue_id);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_cpu_reason_alloc_exception_index(uint8 lchip, uint8 dir, sys_cpu_reason_info_t* p_cpu_rason_info)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    CTC_ERROR_RETURN(sys_usw_nh_get_reason_nhinfo(lchip, p_cpu_rason_info->reason_id, &(p_cpu_rason_info->nexthop_ptr), &(p_cpu_rason_info->dsnh_8w)));

    QOS_LOCK;

    ret = _sys_usw_cpu_reason_alloc_exception_index(lchip, dir, p_cpu_rason_info);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_cpu_reason_free_exception_index(uint8 lchip, uint8 dir, sys_cpu_reason_info_t* p_cpu_rason_info)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = _sys_usw_cpu_reason_free_exception_index(lchip, dir, p_cpu_rason_info);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_cpu_reason_get_info(uint8 lchip, uint16 reason_id, sys_cpu_reason_dest_info_t* p_dest_info)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = _sys_usw_cpu_reason_get_info(lchip, reason_id, p_dest_info);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_cpu_reason_set_info(uint8 lchip, uint16 reason_id, sys_cpu_reason_dest_info_t* p_dest_info)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = _sys_usw_cpu_reason_set_info(lchip, reason_id, p_dest_info);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_cpu_reason_get_reason_info(uint8 lchip, uint8 dir, sys_cpu_reason_info_t* p_cpu_rason_info)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = _sys_usw_cpu_reason_get_reason_info(lchip, dir, p_cpu_rason_info);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_queue_bind_cpu_reason(uint8 lchip, uint16 reason_id)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = _sys_usw_qos_queue_bind_cpu_reason(lchip, reason_id);

    QOS_UNLOCK;

    return ret;
}

/* stacking */
int32
sys_usw_queue_add_for_stacking(uint8 lchip, uint32 gport)
{
    int32 ret = CTC_E_NONE;
    uint32 chan_id[SYS_USW_MAX_CHANEL_NUM_PER_PORT] = {0};
    uint8 index1 = 0;
    uint8 index2 = 0;
    uint8 chan_num = 0;

    SYS_QOS_INIT_CHECK();
    CTC_ERROR_RETURN(sys_usw_port_api_get_channel(lchip, 1, gport, chan_id, &chan_num));
    QOS_LOCK;
    if(CTC_IS_MCHAN_PORT(gport))
    {
        ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_QUE_ADD_FOR_STACKING,
                                 lchip, chan_id[0]);
    }
    else
    {

        for (index1 = 0; index1 < chan_num; index1++)
        {
            if (SYS_COMMON_USELESS_CHANNEL == chan_id[index1])
            {
                ret = CTC_E_INVALID_PORT;
                break;
            }
            ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_QUE_ADD_FOR_STACKING,
                                 lchip, chan_id[index1]);
            if (ret != CTC_E_NONE)
            {
                break;
            }
        }
        if (index1 != chan_num)
        {
            for (index2 = 0; index2 < index1; index2++)
            {
                ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_QUE_REMOVE_FOR_STACKING,
                                     lchip, chan_id[index2]);
            }
        }
    }
    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_queue_remove_for_stacking(uint8 lchip, uint32 gport)
{
    int32 ret = CTC_E_NONE;
    uint32 chan_id[SYS_USW_MAX_CHANEL_NUM_PER_PORT] = {0};
    uint8 index1 = 0;
    uint8 index2 = 0;
    uint8 chan_num = 0;

    SYS_QOS_INIT_CHECK();
    CTC_ERROR_RETURN(sys_usw_port_api_get_channel(lchip, 1, gport, chan_id, &chan_num));
    QOS_LOCK;
    if (CTC_IS_MCHAN_PORT(gport))
    {
        ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_QUE_REMOVE_FOR_STACKING,
                                 lchip, chan_id[0]);
    }
    else
    {
        for (index1 = 0; index1 < chan_num; index1++)
        {
            if (SYS_COMMON_USELESS_CHANNEL == chan_id[index1])
            {
                ret = CTC_E_INVALID_PORT;
                break;
            }
            ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_QUE_REMOVE_FOR_STACKING,
                                 lchip, chan_id[index1]);
            if (ret != CTC_E_NONE)
            {
                break;
            }
        }
        if (index1 != chan_num)
        {
            for (index2 = 0; index2 < index1; index2++)
            {
                ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_QUE_ADD_FOR_STACKING,
                                     lchip, chan_id[index2]);
            }
        }
    }
    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_bind_service_logic_dstport(uint8 lchip, uint16 service_id, uint16 logic_dst_port, uint32 gport,uint32 nexthop_ptr)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_BIND_SERVICE_LOGIC_DSTPORT,
                        lchip, service_id, logic_dst_port, gport, nexthop_ptr);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_unbind_service_logic_dstport(uint8 lchip, uint16 service_id, uint16 logic_dst_port, uint32 gport)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_UNBIND_SERVICE_LOGIC_DSTPORT,
                        lchip, service_id, logic_dst_port, gport);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_bind_service_logic_srcport(uint8 lchip, uint16 service_id, uint16 logic_port)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_BIND_SERVICE_LOGIC_SRCPORT,
                        lchip, service_id, logic_port);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_unbind_service_logic_srcport(uint8 lchip, uint16 service_id, uint16 logic_port)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_UNBIND_SERVICE_LOGIC_SRCPORT,
                        lchip, service_id, logic_port);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_set_drop_resrc_check_mode(uint8 lchip, uint8 mode)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();
    QOS_LOCK;
    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_SET_DROP_RESRC_CHK_MODE,
                        lchip, mode);
    QOS_UNLOCK;
    return ret;
}

int32
sys_usw_qos_set_fc_default_profile(uint8 lchip, uint32 gport)
{
    int32 ret = CTC_E_NONE;
    SYS_QOS_INIT_CHECK();
    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_SET_FC_DEFAULT_PROFILE,
                        lchip, gport);

    QOS_UNLOCK;
    return ret;
}

int32
sys_usw_qos_queue_get_queue_id(uint8 lchip, ctc_qos_queue_id_t* p_queue,uint16* queue_id)
{
    int32 ret = CTC_E_NONE;
    SYS_QOS_INIT_CHECK();
    QOS_LOCK;
    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_QUE_GET_QUE_ID,
                        lchip, p_queue, queue_id);
    QOS_UNLOCK;
    return ret;
}

int32
sys_usw_qos_queue_id_get_queue(uint8 lchip, ctc_qos_queue_id_t* p_queue,uint16 queue_id)
{
    int32 ret = CTC_E_NONE;
    SYS_QOS_INIT_CHECK();
    QOS_LOCK;
    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_QUE_ID_GET_QUE,
                        lchip, p_queue, queue_id);
    QOS_UNLOCK;
    return ret;
}
int32
sys_usw_qos_get_channel_by_queue_id(uint8 lchip, uint16 queue_id, uint16 *channel)
{
    int32 ret = CTC_E_NONE;
    SYS_QOS_INIT_CHECK();
    QOS_LOCK;
    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_GET_CHAN_BY_QUE_ID,
                        lchip, queue_id, channel);
    QOS_UNLOCK;
    return ret;
}

int32
sys_usw_qos_update_cpu_reason(uint8 lchip, uint8 remote_gchip, uint8 trunk_id)
{
    int32 ret = CTC_E_NONE;
    SYS_QOS_INIT_CHECK();
    QOS_LOCK;
    ret = sys_usw_exception_update_trunk_by_rchip(lchip, remote_gchip, trunk_id);
    QOS_UNLOCK;
    return ret;
}

int32
sys_usw_queue_set_egs_resrc_guarantee(uint8 lchip, uint8 enable)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();
    QOS_LOCK;
    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_SET_EGS_RESRC_GUARANTEE,
                        lchip, enable);
    QOS_UNLOCK;
    return ret;
}

int32
sys_usw_queue_traverse_queue_node(uint8 lchip, uint16 lport,
                                      int32 (*fn)(uint8 lchip, sys_traverse_t* data),
                                      void* user_data)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();
    QOS_LOCK;
    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_TRAVERSE_QUEUE_NODE,
                        lchip, lport, fn, user_data);
    QOS_UNLOCK;
    return ret;
}

int32
sys_usw_qos_set_port_dynamic_switch(uint8 lchip, uint16 lport, uint8 index)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();
    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NONE, SYS_QOS_API_SET_PORT_DYNAMIC_SWITCH, lchip, lport, index);

    QOS_UNLOCK;
    return ret;
}

int32
sys_usw_set_monitor_drop_discard_enable(uint8 lchip, uint8 enable)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();
    QOS_LOCK;
    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_SET_MONITOR_DROP_DISCARD, lchip, enable);
    QOS_UNLOCK;
    return ret;
}

#define __3_QOS_SHOW_API__
int32
sys_usw_qos_domain_map_default(uint8 lchip)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = _sys_usw_qos_domain_map_default(lchip);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_domain_map_dump(uint8 lchip, uint8 domain, uint8 type)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = _sys_usw_qos_domain_map_dump(lchip, domain, type);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_table_map_dump(uint8 lchip, uint8 table_map_id, uint8 type)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = _sys_usw_qos_table_map_dump(lchip, table_map_id, type);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_policer_dump(uint8 type, uint8 dir, uint8 lchip, uint32 start, uint32 end, uint8 detail)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = _sys_usw_qos_policer_dump(type, dir, lchip, start, end, detail);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_queue_dump(uint8 lchip, uint16 start, uint16 end, uint8 detail)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_QUE_DUMP,
                        lchip, start, end, detail);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_group_dump(uint8 lchip, uint32 start, uint32 end, uint8 detail)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_GROUP_DUMP,
                        lchip, start, end, detail);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_port_dump(uint8 lchip, uint32 start, uint32 end, uint8 detail)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_PORT_DUMP,
                        lchip, start, end, detail);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_service_dump(uint8 lchip, uint16 service_id, uint32 gport)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_SERVICE_DUMP,
                        lchip, service_id, gport);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_cpu_reason_dump(uint8 lchip, uint16 start, uint16 end, uint8 detail)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = _sys_usw_qos_cpu_reason_dump(lchip, start, end, detail);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_dump_status(uint8 lchip)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_DUMP_STATUS,
                        lchip);

    QOS_UNLOCK;

    return ret;
}

#define __4_QOS_CTC_API__

/*policer*/
int32
sys_usw_qos_set_policer(uint8 lchip, ctc_qos_policer_t* p_policer)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = sys_usw_qos_policer_set(lchip, p_policer);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_get_policer(uint8 lchip, ctc_qos_policer_t* p_policer)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = sys_usw_qos_policer_get(lchip, p_policer);

    QOS_UNLOCK;

    return ret;
}

/*shape*/
int32
sys_usw_qos_set_shape(uint8 lchip, ctc_qos_shape_t* p_shape)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_SET_SHAPE,
                        lchip, p_shape);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_get_shape(uint8 lchip, ctc_qos_shape_t* p_shape)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_GET_SHAPE,
                        lchip, p_shape);

    QOS_UNLOCK;

    return ret;
}
/*schedule*/
int32
sys_usw_qos_set_sched(uint8 lchip, ctc_qos_sched_t* p_sched)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_SET_SCHED,
                        lchip, p_sched);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_get_sched(uint8 lchip, ctc_qos_sched_t* p_sched)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_GET_SCHED,
                        lchip, p_sched);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_create_sched_group(uint8 lchip, ctc_qos_sched_group_id_t* p_sched_group)
{
    int32 ret = CTC_E_NONE;

    if(!DRV_FROM_TMM(lchip))
    {
        return CTC_E_NOT_SUPPORT;
    }
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    if (MCHIP_QOS(lchip)->qos_sch_create_sched_group)
    {
        if (CTC_QOS_SCHED_GROUP_LVL_Q == p_sched_group->level || CTC_QOS_SCHED_GROUP_LVL_R == p_sched_group->level)
        {
            if (!sys_usw_chip_is_local(lchip, CTC_MAP_GPORT_TO_GCHIP(p_sched_group->gport)))
            {
                QOS_UNLOCK;
                return CTC_E_INVALID_CHIP_ID;
            }
        }
        ret = MCHIP_QOS(lchip)->qos_sch_create_sched_group(lchip, p_sched_group, SYS_COMMON_USELESS_CHANNEL);
    }

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_destroy_sched_group(uint8 lchip, ctc_qos_sched_group_id_t* p_sched_group)
{
    int32 ret = CTC_E_NONE;
    if(!DRV_FROM_TMM(lchip))
    {
        return CTC_E_NOT_SUPPORT;
    }
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    if (MCHIP_QOS(lchip)->qos_sch_destroy_sched_group)
    {
        ret = MCHIP_QOS(lchip)->qos_sch_destroy_sched_group(lchip, p_sched_group);
    }

    QOS_UNLOCK;

    return ret;
}

/*mapping*/
int32
sys_usw_qos_set_domain_map(uint8 lchip, ctc_qos_domain_map_t* p_domain_map)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = sys_usw_qos_domain_map_set(lchip, p_domain_map);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_get_domain_map(uint8 lchip, ctc_qos_domain_map_t* p_domain_map)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = sys_usw_qos_domain_map_get(lchip, p_domain_map);

    QOS_UNLOCK;

    return ret;
}


int32
sys_usw_qos_set_global_config_pre(uint8 lchip, ctc_qos_glb_cfg_t* p_glb_cfg, sys_nh_info_dsnh_t *p_nhinfo, sys_cpu_reason_dest_info_t *p_dest_info)
{
    int32 ret = CTC_E_NONE;
    uint16 lport = 0;
    uint8 nh_type = 0;
    if (p_glb_cfg->u.drop_monitor.nhid)
    {
        CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo(lchip, p_glb_cfg->u.drop_monitor.nhid, p_nhinfo, 0));
        if (p_nhinfo->nh_entry_type == SYS_NH_TYPE_MCAST || p_nhinfo->nh_entry_type == SYS_NH_TYPE_TOCPU || p_nhinfo->nh_entry_type == SYS_NH_TYPE_APS ||
            p_nhinfo->nh_entry_type == SYS_NH_TYPE_ECMP || p_nhinfo->nh_entry_type == SYS_NH_TYPE_DROP || p_nhinfo->aps_en || p_nhinfo->is_ecmp_intf)
        {
            return CTC_E_INVALID_PARAM;
        }
    }
    else
    {
        lport = CTC_MAP_GPORT_TO_LPORT(p_glb_cfg->u.drop_monitor.dst_gport);
        nh_type = (MCHIP_CAP(SYS_CAP_RSV_PORT_MOD_ID) != lport) ? SYS_NH_RES_OFFSET_TYPE_BYPASS_NH : SYS_NH_RES_OFFSET_TYPE_BRIDGE_NH;
        CTC_ERROR_RETURN(sys_usw_nh_get_resolved_offset(lchip, nh_type, &p_nhinfo->dsnh_offset));
    }
    
    if (CTC_IS_CPU_PORT(p_glb_cfg->u.drop_monitor.nhid ? p_nhinfo->gport : p_glb_cfg->u.drop_monitor.dst_gport))
    {
        QOS_LOCK;
        CTC_ERROR_RETURN_WITH_UNLOCK(sys_usw_qos_alloc_monitor_drop_reason_queue_id(lchip, p_dest_info), p_usw_qos_master[lchip]->p_qos_mutex);
        QOS_UNLOCK;
        ret = sys_usw_cpu_reason_update_exception(lchip, CTC_PKT_CPU_REASON_QUEUE_DROP_PKT, p_dest_info);
        if (ret)
        {
            QOS_LOCK;
            sys_usw_qos_free_monitor_drop_reason_queue_id(lchip);
            QOS_UNLOCK;
            return ret;
        }
        p_nhinfo->ecmp_group_id = p_dest_info->sub_queue_id;/*temp reuse as sub queue id*/
    }
    return CTC_E_NONE;
}

/*global param*/
int32
sys_usw_qos_set_global_config(uint8 lchip, ctc_qos_glb_cfg_t* p_glb_cfg)
{
    int32 ret = CTC_E_NONE;
    sys_nh_info_dsnh_t nhinfo;
    sys_cpu_reason_dest_info_t dest_info;        

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_QOS_INIT_CHECK();

    /*to prevent qos&nh deadlock, put get nh code here*/
    sal_memset(&nhinfo, 0, sizeof(nhinfo));
    sal_memset(&dest_info, 0, sizeof(dest_info));
    if(p_glb_cfg->cfg_type == CTC_QOS_GLB_CFG_QUEUE_DROP_MONITOR_EN)
    {
        CTC_ERROR_RETURN(sys_usw_qos_set_global_config_pre(lchip, p_glb_cfg, &nhinfo, &dest_info));
    }
    QOS_LOCK;

    switch (p_glb_cfg->cfg_type)
    {
    case CTC_QOS_GLB_CFG_POLICER_EN:
        ret = sys_usw_qos_set_policer_update_enable(lchip, p_glb_cfg->u.value);
        break;

    case CTC_QOS_GLB_CFG_POLICER_STATS_EN:
        ret = CTC_E_NOT_SUPPORT;
        break;

    case  CTC_QOS_GLB_CFG_POLICER_IPG_EN:
        ret = sys_usw_qos_set_policer_ipg_enable(lchip, p_glb_cfg->u.value);
        break;

    case CTC_QOS_GLB_CFG_POLICER_SEQENCE_EN:
        ret = CTC_E_NOT_SUPPORT;
        break;

    case  CTC_QOS_GLB_CFG_QUE_SHAPE_EN:
        ret = sys_usw_qos_set_queue_shape_enable(lchip, p_glb_cfg->u.value);
        break;

    case  CTC_QOS_GLB_CFG_GROUP_SHAPE_EN:
        ret = sys_usw_qos_set_group_shape_enable(lchip, p_glb_cfg->u.value);
        break;

    case  CTC_QOS_GLB_CFG_PORT_SHAPE_EN:
        ret = sys_usw_qos_set_port_shape_enable(lchip, p_glb_cfg->u.value);
        break;

    case CTC_QOS_GLB_CFG_SHAPE_IPG_EN:
        ret = sys_usw_qos_set_shape_ipg_enable(lchip, p_glb_cfg->u.value);
        break;

    case CTC_QOS_GLB_CFG_POLICER_FLOW_FIRST_EN:

        if (DRV_IS_DUET2(lchip))
        {
            ret = CTC_E_NOT_SUPPORT;
        }
        else if ( 0 == p_usw_qos_policer_master[lchip]->policer_merge_mode)
        {
            SYS_QOS_POLICER_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Qos] Policer not ready to set flow first enable \n");
            ret = CTC_E_INVALID_CONFIG;
        }
        else
        {
            ret = sys_usw_qos_set_policer_flow_first(lchip, (p_glb_cfg->u.value >> 16) & 0xFFFF,
                                                            (p_glb_cfg->u.value & 0xFFFF));
        }
        break;

    case CTC_QOS_GLB_CFG_QUE_STATS_EN:
        ret = CTC_E_NOT_SUPPORT;
        break;

    case CTC_QOS_GLB_CFG_PHB_MAP:
        ret = sys_usw_qos_set_phb(lchip, &p_glb_cfg->u.phb_map);
        break;
    case CTC_QOS_GLB_CFG_POLICER_HBWP_SHARE_EN:
        ret = CTC_E_NOT_SUPPORT;
        break;

    case CTC_QOS_GLB_CFG_POLICER_MARK_ECN_EN:
        ret = CTC_E_NOT_SUPPORT;
        break;

    case CTC_QOS_GLB_CFG_TABLE_MAP:
        ret = sys_usw_qos_table_map_set(lchip, &p_glb_cfg->u.table_map);
        break;
    case CTC_QOS_GLB_CFG_OBM_MAP:
        ret = sys_usw_qos_obm_map_set(lchip, &p_glb_cfg->u.obm_map);
        break;
    case CTC_QOS_GLB_CFG_ECN_EN:
        ret = sys_usw_qos_set_ecn_enable(lchip, p_glb_cfg->u.value);
        break;
    case CTC_QOS_GLB_CFG_POLICER_PORT_STBM_EN:
        ret = sys_usw_qos_set_port_policer_stbm_enable(lchip, p_glb_cfg->u.value);
        break;
    case CTC_QOS_GLB_CFG_FAST_ECN_THRD:
        ret = sys_usw_qos_set_fast_ecn(lchip, p_glb_cfg->u.value);
        break;
    default:
        ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_SET_GLB_CFG, lchip, p_glb_cfg, &nhinfo);
        break;
    }

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_get_global_config(uint8 lchip, ctc_qos_glb_cfg_t* p_glb_cfg)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    switch (p_glb_cfg->cfg_type)
    {
    case CTC_QOS_GLB_CFG_TABLE_MAP:
        ret = sys_usw_qos_table_map_get(lchip, &p_glb_cfg->u.table_map);
        break;
    case CTC_QOS_GLB_CFG_OBM_MAP:
        ret = sys_usw_qos_obm_map_get(lchip, &p_glb_cfg->u.obm_map);
        break;
    case CTC_QOS_GLB_CFG_ECN_EN:
        ret = sys_usw_qos_get_ecn_enable(lchip, &p_glb_cfg->u.value);
        break;
    case CTC_QOS_GLB_CFG_PHB_MAP:
        ret = sys_usw_qos_get_phb(lchip, &p_glb_cfg->u.phb_map);
        break;
    case  CTC_QOS_GLB_CFG_QUE_SHAPE_EN:
        ret = sys_usw_qos_get_queue_shape_enable(lchip, &p_glb_cfg->u.value);
        break;
    case  CTC_QOS_GLB_CFG_GROUP_SHAPE_EN:
        ret = sys_usw_qos_get_group_shape_enable(lchip, &p_glb_cfg->u.value);
        break;
    case  CTC_QOS_GLB_CFG_PORT_SHAPE_EN:
        ret = sys_usw_qos_get_port_shape_enable(lchip, &p_glb_cfg->u.value);
        break;
    case CTC_QOS_GLB_CFG_FAST_ECN_THRD:
        ret = sys_usw_qos_get_fast_ecn(lchip, &p_glb_cfg->u.value);
        break;
    default:
        ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_GET_GLB_CFG, lchip, p_glb_cfg);
        break;
    }

    QOS_UNLOCK;

    return ret;
}

/*queue*/
int32
sys_usw_qos_set_queue(uint8 lchip, ctc_qos_queue_cfg_t* p_que_cfg)
{
    int32 ret = CTC_E_NONE;
    ctc_qos_queue_cpu_reason_dest_t* p_reason_dest = &p_que_cfg->value.reason_dest;
    sys_cpu_reason_dest_info_t dest_info;
    sal_memset(&dest_info, 0, sizeof(sys_cpu_reason_dest_info_t));

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_QOS_INIT_CHECK();

    /*to prevent qos deadlock, put acl code here*/
    if (CTC_QOS_QUEUE_CFG_QUEUE_REASON_DEST == p_que_cfg->type)
    {
        if (MCHIP_FEATURE_CAP(lchip,CTC_FEATURE_WLAN) && (CTC_PKT_CPU_REASON_WLAN_CHECK_ERR == p_reason_dest->cpu_reason))
        {
            CTC_ERROR_RETURN(sys_usw_acl_set_wlan_crypt_error_to_cpu_en(lchip, (CTC_PKT_CPU_REASON_TO_DROP != p_reason_dest->dest_type)?1:0));
        }
        else if (MCHIP_FEATURE_CAP(lchip,CTC_FEATURE_DOT1AE) && (CTC_PKT_CPU_REASON_DOT1AE_CHECK_ERR == p_reason_dest->cpu_reason))
        {
            CTC_ERROR_RETURN(sys_usw_acl_set_dot1ae_crypt_error_to_cpu_en(lchip, (CTC_PKT_CPU_REASON_TO_DROP != p_reason_dest->dest_type)?1:0));
        }
    }

    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_SET_QUE,
                        lchip, p_que_cfg, &dest_info);

    QOS_UNLOCK;

    /*update dest, put code here for qos and nh deadlock*/
    if(CTC_QOS_QUEUE_CFG_QUEUE_REASON_DEST == p_que_cfg->type || CTC_QOS_QUEUE_CFG_QUEUE_REASON_MAP == p_que_cfg->type)
    {
        ret = ret ? ret : sys_usw_cpu_reason_update_exception(lchip, p_reason_dest->cpu_reason, &dest_info);
    }

    /*to prevent qos deadlock, put acl code here*/
    if (ret)
    {
        if (CTC_QOS_QUEUE_CFG_QUEUE_REASON_DEST == p_que_cfg->type)
        {
            if (MCHIP_FEATURE_CAP(lchip,CTC_FEATURE_WLAN) && (CTC_PKT_CPU_REASON_WLAN_CHECK_ERR == p_reason_dest->cpu_reason))
            {
                sys_usw_acl_set_wlan_crypt_error_to_cpu_en(lchip, (CTC_PKT_CPU_REASON_TO_DROP != p_reason_dest->dest_type)?0:1);
            }
            else if (MCHIP_FEATURE_CAP(lchip,CTC_FEATURE_DOT1AE) && (CTC_PKT_CPU_REASON_DOT1AE_CHECK_ERR == p_reason_dest->cpu_reason))
            {
                sys_usw_acl_set_dot1ae_crypt_error_to_cpu_en(lchip, (CTC_PKT_CPU_REASON_TO_DROP != p_reason_dest->dest_type)?0:1);
            }
        }
    }

    return ret;
}

/*queue*/
int32
sys_usw_qos_get_queue(uint8 lchip, ctc_qos_queue_cfg_t* p_que_cfg)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_QOS_INIT_CHECK();
    QOS_LOCK;
    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_GET_QUE,
                        lchip, p_que_cfg);
    QOS_UNLOCK;
    return ret;
}
/*drop*/
int32
sys_usw_qos_set_drop_scheme(uint8 lchip, ctc_qos_drop_t* p_drop)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_SET_DROP,
                        lchip, p_drop);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_get_drop_scheme(uint8 lchip, ctc_qos_drop_t* p_drop)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_GET_DROP,
                        lchip, p_drop);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_queue_set_resrc_use_cnt_min(uint8 lchip, uint8 min)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = _sys_usw_queue_set_resrc_use_cnt_min(lchip, min);

    QOS_UNLOCK;

    return ret;
}

/*Resrc*/
int32
sys_usw_qos_set_resrc(uint8 lchip, ctc_qos_resrc_t* p_resrc)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_SET_RESRC,
                        lchip, p_resrc);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_get_resrc(uint8 lchip, ctc_qos_resrc_t* p_resrc)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_GET_RESRC,
                        lchip, p_resrc);

    QOS_UNLOCK;

    return ret;
}

/*stats*/
int32
sys_usw_qos_query_pool_stats(uint8 lchip, ctc_qos_resrc_pool_stats_t* p_stats)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_QUERY_POOL_STATS,
                        lchip, p_stats);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_query_queue_stats(uint8 lchip, ctc_qos_queue_stats_t* p_queue_stats)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_QUERY_QUE_STATS,
                        lchip, p_queue_stats);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_clear_queue_stats(uint8 lchip, ctc_qos_queue_stats_t* p_queue_stats)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_CLEAR_QUE_STATS,
                        lchip, p_queue_stats);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_query_policer_stats(uint8 lchip, ctc_qos_policer_stats_t* p_policer_stats)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = sys_usw_qos_policer_stats_query(lchip, p_policer_stats);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_clear_policer_stats(uint8 lchip, ctc_qos_policer_stats_t* p_policer_stats)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = sys_usw_qos_policer_stats_clear(lchip, p_policer_stats);

    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_query_stats(uint8 lchip, ctc_qos_stats_type_t type, void* p_stats)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_QUERY_STATS,
                        lchip, type, p_stats);


    QOS_UNLOCK;

    return ret;
}

int32
sys_usw_qos_clear_stats(uint8 lchip, ctc_qos_stats_type_t type, void* p_stats)
{
    int32 ret = CTC_E_NONE;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_QOS_INIT_CHECK();

    QOS_LOCK;

    ret = SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_CLEAR_STATS,
                        lchip, type, p_stats);


    QOS_UNLOCK;

    return ret;
}

/**
 @brief Set flow control of port
*/
int32
sys_usw_qos_set_flow_ctl_en(uint8 lchip, void* p_fc_prop)
{
	int32 ret = CTC_E_NONE;
    ctc_port_fc_prop_t *fc_prop = (ctc_port_fc_prop_t *)p_fc_prop;
    uint8 recover_state = 0;
    uint8 pfc_class = 0;

    CTC_PTR_VALID_CHECK(fc_prop);

	SYS_QOS_INIT_CHECK();
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

	QOS_LOCK;
    if ((CTC_INGRESS == fc_prop->dir) || (CTC_BOTH_DIRECTION == fc_prop->dir))
    {
        pfc_class = fc_prop->priority_class_bmp ? fc_prop->pfc_class : fc_prop->priority_class;
        CTC_ERROR_GOTO(sys_usw_qos_fcdl_get_recover_state(lchip, fc_prop->gport, pfc_class, &recover_state), ret, error0);
        if (recover_state)
        {
            ret = CTC_E_NOT_READY;
            goto error0;
        }
    }
    ret = SYS_CB(SYS_CB_QOS_SET_FLOW_CONTROL, lchip, (void*)p_fc_prop, 0);

error0:
    QOS_UNLOCK;
    return ret;
}

/**
 @brief Get flow control of port
*/
int32
sys_usw_qos_get_flow_ctl_en(uint8 lchip, void* p_fc_prop)
{
	int32 ret = CTC_E_NONE;
    ctc_port_fc_prop_t *fc_prop = (ctc_port_fc_prop_t *)p_fc_prop;
    uint8 recover_state = 0;

    CTC_PTR_VALID_CHECK(fc_prop);

	SYS_QOS_INIT_CHECK();
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

	QOS_LOCK;
    if ((CTC_INGRESS == fc_prop->dir) || (CTC_BOTH_DIRECTION == fc_prop->dir))
    {
        CTC_ERROR_GOTO(sys_usw_qos_fcdl_get_recover_state(lchip, fc_prop->gport, fc_prop->priority_class, &recover_state), ret, error0);
        if (recover_state)
        {
            ret = CTC_E_NOT_READY;
            goto error0;
        }
    }
    ret = SYS_CB(SYS_CB_QOS_GET_FLOW_CONTROL, lchip, (void*)fc_prop);

error0:
    QOS_UNLOCK;
    return ret;
}

#define __5_QOS_INIT__

/*init*/
int32
sys_usw_qos_init(uint8 lchip, void* p_glb_parm)
{
    int32 ret = CTC_E_NONE;

    LCHIP_CHECK(lchip);
    CTC_PTR_VALID_CHECK(p_glb_parm);

    if (NULL != p_usw_qos_master[lchip])
    {
        return CTC_E_NONE;
    }
    SYS_VCHIP_MASTER_INIT_GLOBAL(lchip, p_usw_qos_master);
    /* create qos master */
    p_usw_qos_master[lchip] = (sys_qos_master_t *)mem_malloc(MEM_QUEUE_MODULE, sizeof(sys_qos_master_t));
    if (NULL == p_usw_qos_master[lchip])
    {
        ret = CTC_E_NO_MEMORY;
        goto error0;
    }

    sal_memset(p_usw_qos_master[lchip], 0, sizeof(sys_qos_master_t));

    ret = sal_mutex_create(&p_usw_qos_master[lchip]->p_qos_mutex);
    if (ret || !p_usw_qos_master[lchip]->p_qos_mutex)
    {
        ret = CTC_E_NO_MEMORY;
        goto error1;
    }
    /*sys qos api callback register*/
    if (MCHIP_QOS(lchip)->qos_api_register)
    {
        MCHIP_QOS(lchip)->qos_api_register(lchip, (void**)&p_usw_qos_master[lchip]->api_cb);
    }
    /*qos module api init*/
    CTC_ERROR_GOTO(SYS_QOS_API_CB(CTC_E_NOT_SUPPORT, SYS_QOS_API_INIT, lchip, p_glb_parm), ret, error2);

    /* warmboot register */
    CTC_ERROR_GOTO(sys_usw_wb_sync_register_cb(lchip, CTC_FEATURE_QOS,SYS_WB_APPID_QOS_SUBID_MAX, sys_usw_qos_wb_sync), ret, error3);
    /* dump db register */
    CTC_ERROR_GOTO(sys_usw_dump_db_register_cb(lchip, CTC_FEATURE_QOS, sys_usw_qos_dump_db), ret, error3);
    /* warmboot data restore */
    if (CTC_WB_ENABLE(lchip) && (CTC_WB_STATUS(lchip) == CTC_WB_STATUS_RELOADING))
    {
        CTC_ERROR_GOTO(sys_usw_qos_wb_restore(lchip), ret, error3);
    }

    if (CTC_WB_ENABLE(lchip))
    {
        _sys_usw_qos_wb_init(lchip);
    }

    CTC_ERROR_GOTO(SYS_CB_REGISTER(lchip, SYS_CB_QOS_SET_PORT_DYNAMIC_SWITCH, sys_usw_qos_set_port_dynamic_switch), ret, error3);

    sys_usw_mchip_set_feature_en(lchip,CTC_FEATURE_QOS);
    return CTC_E_NONE;
error3:
    SYS_QOS_API_CB(CTC_E_NONE, SYS_QOS_API_DEINIT, lchip);
error2:
    sal_mutex_destroy(p_usw_qos_master[lchip]->p_qos_mutex);
error1:
    mem_free(p_usw_qos_master[lchip]);
error0:
    return ret;
}

/*deinit*/
int32
sys_usw_qos_deinit(uint8 lchip)
{
    LCHIP_CHECK(lchip);

    if (NULL == p_usw_qos_master[lchip])
    {
        return CTC_E_NONE;
    }
    SYS_VCHIP_MASTER_DEINIT_GLOBAL(lchip, p_usw_qos_master);

    SYS_QOS_API_CB(CTC_E_NONE, SYS_QOS_API_DEINIT, lchip);

    sal_mutex_destroy(p_usw_qos_master[lchip]->p_qos_mutex);

    mem_free(p_usw_qos_master[lchip]);

    sys_usw_wb_sync_register_cb(lchip, CTC_FEATURE_QOS,0, NULL);
    sys_usw_dump_db_register_cb(lchip, CTC_FEATURE_QOS, NULL);
    SYS_CB_REGISTER(lchip, SYS_CB_QOS_UPDATE_TRUNK_BY_RCHIP, NULL);
    return CTC_E_NONE;
}

